#ifndef __TABLE1_H__
#define __TABLE1_H__

#include "yid.h"
#include "lich_id.h"
#include "table_proto.h"
#include "fileinfo.h"
#include "fs_proto.h"
#include "chunk.h"
#include "plock.h"
#include "chunk_proto.h"
#include "volume_proto_eclog.h"
#include "cluster.h"
#include "lease.h"

#include "lich_ctx.h"
#include "lsv.h"
#include "token_bucket.h"
#include "lichstor.h"
#include "lock_table.h"
#include "profile.h"

#define FILE_PROTO_LOCK 128

/* Throt type */
#define THROT_READ  "throt_read"
#define THROT_WRITE "throt_write"
#define THROT_IOPS  LICH_SYSTEM_ATTR_THROT_IOPS
#define THROT_BW    LICH_SYSTEM_ATTR_THROT_BW
#define ANALYSIS_LATENCY        LICH_SYSTEM_ATTR_LATENCY

#define TABLE1_EXT_MAX_NUM 2

#pragma pack(8)

typedef struct {
        uint32_t chunk_count;
        char chkinfo_array[TABLE1_EXT_MAX_NUM][CHKINFO_MAX];
} table1_ext_info_t;

/*table1*/

typedef struct {
        int lock;
        vfm_t *vfm;
} vfm_mem_t;

typedef struct __table1 {
        plock_t rwlock; //lock2 for fileinfo,table_proto,table_array

        void *volume_proto;

        // L1 chunk: table1对应的vol chunk
        fileid_t chkid;
        // serialization in info area
        fileinfo_t fileinfo;
        // L1 first chunk, like vol.x.0
        table_proto_t *table_proto;

        // 持久化数据，存在于L1第一个chunk的info区
        table1_ext_info_t ext_info;
        // L1 rest chunks, like vol.x.1-x
        table_proto_t *ext[TABLE1_EXT_MAX_NUM];

        // L2 chunk: subvol的数量，数组中每一项对应一个subvol chunk (table_proto_t)
        int table_count;
        // L2 chunks like subvol.x.0-x
        table_proto_t **table_array;
        vfm_mem_t *vfm_array;

        // 所在pool
        fileid_t parent;
        // pool controller所在nid
        nid_t parentnid;

        char source[MAX_NAME_LEN];

        time_t ltime;

#ifdef USE_ROW2
        lsv_volume_proto_t lsv_info;
#endif

        char pool[MAX_NAME_LEN];

        int (*extend)(struct __table1 *table1, int idx);//temporary
        int (*get_table2)(struct __table1 *table1, table_proto_t **_table,
                          const chkid_t *tableid);
        int (*get_table2_nolock)(struct __table1 *table1, table_proto_t **_table,
                          const chkid_t *tableid);
        int (*create_table2)(struct __table1 *table1, table_proto_t **_table,
                          const chkid_t *tableid, void *_volume_proto);

        int (*stat)(struct __table1 *table1, filestat_t *filestat);

        int (*table_read)(struct __table1 *, const chkid_t *chkid, buffer_t *buf, size_t size, off_t offset);
        int (*table_write)(struct __table1 *, const chkid_t *chkid, const buffer_t *buf, size_t size, off_t offset);

        int (*setattr)(struct __table1 *, fileinfo_t *_fileinfo, const setattr_t *setattr);
        int (*getattr)(struct __table1 *, fileinfo_t *fileinfo);
        int (*loadattr)(struct __table1 *, void *_volume_proto);

        int (*rdlock)(struct __table1 *);
        int (*wrlock)(struct __table1 *);
        void (*unlock)(struct __table1 *);

        int (*chunk_getinfo)(struct __table1 *table1, const chkid_t *chkid,
                             chkinfo_t *chkinfo);
        int (*chunk_iterator)(struct __table1 *, func2_t func2, void *_arg);
        int (*chunk_unintact)(struct __table1 *, func3_t func3, void *_arg);

        int (*chunk_set)(struct __table1 *table1, const chkid_t *chkid,
                         const nid_t *nid, int status, void *volume_proto);
        int (*chunk_check)(struct __table1 *table1, const chkid_t *chkid, int op, int *oflags);
        int (*chunk_sync)(struct __table1 *table1, const chkid_t *chkid, void *volume_proto, int *oflags);
        int (*move)(struct __table1 *table1, const chkid_t *chkid, const nid_t *nid, int count);

        int (*chunk_cleanup)(struct __table1 *, const chkid_t *chkid, const nid_t *_nid,
                             uint64_t meta_version, void *);
        int (*chunk_update)(struct __table1 *, const chkinfo_t *chkinfo, const nid_t *owner, uint64_t info_version);
        int (*chunk_reject)(struct __table1 *, const chkid_t *chkid, const nid_t *bad, chkinfo_t *chkinfo);

        int (*xattr_set)(struct __table1 *, const char *key, const char *value,
                         uint32_t valuelen, int flag);
        int (*xattr_get)(struct __table1 *, const char *key, char *value,
                         int *valuelen);
        int (*xattr_list)(struct __table1 *, char *buf, int *buflen);
        int (*xattr_remove)(struct __table1 *, const char *key);

        int (*snapshot_isempty)(struct __table1 *, int *empty);
        int (*snapshot_check)(struct __table1 *, const char *name);

        int (*snapshot_create)(struct __table1 *, const char *name, int p, const char *_site, int force);
        int (*snapshot_remove)(struct __table1 *, const char *key);

        int (*snapshot_list)(struct __table1 *, void *buf, int *len);
        int (*snapshot_iterator)(struct __table1 *, func2_t func2, void *_arg);
        int (*snapshot_unintact)(struct __table1 *, func3_t func3, void *_arg);
        int (*snapshot_iterator2)(struct __table1 *, func_int2_t func2, void *_arg);
        int (*snapshot_listchild)(struct __table1 *, uint64_t snap_from, struct list_head *list);
        int (*snapshot_listparent)(struct __table1 *, uint64_t snap_version, struct list_head *list);
        int (*snapshot_last)(struct __table1 *, nid_t *nid, fileid_t *fileid, char *name, uint64_t *snap_version);
        int (*snapshot_getinfo)(struct __table1 *, const fileid_t *fileid, chkinfo_t *chkinfo);
        int (*snapshot_getversion)(struct __table1 *, const chkid_t *chkid, uint64_t *snap_version);
        int (*snapshot_getbyversion)(struct __table1 *, uint64_t snap_version, chkinfo_t *chkinfo, char *name);
        int (*snapshot_lookup)(struct __table1 *, const char *name, chkinfo_t *chkinfo, uint64_t *snap_version);

        int (*snapshot_protect)(struct __table1 *, const int on);
        int (*snapshot_rename)(struct __table1 *, const char *name, const char *to);
        int (*snapshot_updateparent)(struct __table1 *, const char *name, const uint64_t from);
        int (*snapshot_setfrom)(struct __table1 *, const uint64_t from);
        int (*snapshot_auto_remove)(struct __table1 *, uint64_t snap_version, int force);

        int (*snapshot_next)(struct __table1 *, const chkid_t *chkid, chkid_t *next, char *name, uint64_t *snap_version);
        int (*snapshot_prev)(struct __table1 *, const chkid_t *chkid, chkid_t *prev, char *name, uint64_t *snap_version);

        int (*snapshot_rollback)(struct __table1 *, const char *name);
        int (*snapshot_rollback_bh)(struct __table1 *, buffer_t *buf);

        int (*snapshot_flat)(struct __table1 *, int on);

        int (*vfm_stat)(struct __table1 *table1, int *count);
} table1_t;

#pragma pack()

#endif
